/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.mahumLogs.beans;

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 * @author apo
 */
import com.jcraft.jsch.Channel;
import com.mahumLogs.backedbeans.*;
import com.mahumLogs.backedbeans.Configuration;
import com.mahumLogs.ejb.PeriodicScanEJB;
import com.mahumLogs.model.PromotionDataModel;
import com.mahumLogs.utils.DataValidation;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.annotation.Resource;
import javax.enterprise.context.RequestScoped;
import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.model.SelectItem;
import javax.inject.Inject;
import javax.inject.Named;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import javax.transaction.UserTransaction;
import org.primefaces.context.RequestContext;
import org.primefaces.event.RowEditEvent;

/**
 *
 * @author Edouard
 */
@Named
@RequestScoped
public class AdministrationBean implements Serializable {

    @Resource
    private UserTransaction tx;
    @PersistenceContext
    private EntityManager em;
    @Inject
    private SessionBean sessionBean;
    @Inject
    private ConfigurationBean configBean;
    @Inject
    private MachineBean machineBean;
    private @Inject
    ClientSSHBean clientSSH;
    private String password;
    private String confirmationPassword;
    private List<Configuration> configs;
    private List<Etudiant> etudiants;
    private Etudiant etudiant;
    private List<SelectItem> listeChoixPromotion;
    private List<Promotion> listePromotionFilter;
    private List<Promotion> promotions;
    private Promotion promotion;
    private PromotionDataModel promosModel;
    private List<Promotion> selectedPromotions;
    private List<Etudiant> selectedEtudiant;
    private Machine machine;
    private List<Machine> lesMachines = new ArrayList();

    /**
     * Constructeur
     */
    public AdministrationBean() {
        this.configs = new ArrayList();
        this.etudiants = new ArrayList();
        this.etudiant = new Etudiant();
        this.listeChoixPromotion = new ArrayList();
        this.promotions = new ArrayList();
        this.promotion = new Promotion();
        this.selectedPromotions = new ArrayList();
        this.machine = new Machine();
        this.lesMachines = new ArrayList();
    }

    /**
     * @return sessionBean
     */
    public SessionBean getSessionBean() {
        return sessionBean;
    }

    /**
     *
     * @param sessionBean
     */
    public void setSessionBean(SessionBean sessionBean) {
        this.sessionBean = sessionBean;
    }

    /**
     * @return password
     */
    public String getPassword() {
        return password;
    }

    /**
     * @param password
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * @return confirmationPassword
     */
    public String getConfirmationPassword() {
        return confirmationPassword;
    }

    /**
     *
     * @param confirmationPassword
     */
    public void setConfirmationPassword(String confirmationPassword) {
        this.confirmationPassword = confirmationPassword;
    }

    /**
     *
     * @return configs (List))
     */
    public List<Configuration> getConfigs() {
        if (this.configs == null || this.configs.isEmpty()) {
            this.configs = em.createQuery("SELECT c FROM Configuration c WHERE c.modifiable=1").getResultList();
        }
        return configs;
    }

    /**
     *
     * @return machine
     */
    public Machine getMachine() {
        return machine;
    }

    /**
     *
     * @param machine
     */
    public void setMachine(Machine machine) {
        this.machine = machine;
    }

    /**
     * *
     * @param configs
     */
    public void setConfigs(List<Configuration> configs) {
        this.configs = configs;
    }

    /**
     *
     * @return etudiants (List)
     */
    public List<Etudiant> getEtudiants() {
        if (this.etudiants == null || this.etudiants.isEmpty()) {
            this.etudiants = em.createQuery("SELECT e FROM Etudiant e ORDER BY e.nom,e.prenom").getResultList();

            //creation de la liste de choix
            this.listeChoixPromotion.clear();
            this.listeChoixPromotion.add(new SelectItem("", "Choisissez..."));
            List<Promotion> promotions = em.createQuery("SELECT p from Promotion p ORDER BY p.libelle").getResultList();
            for (Promotion p : promotions) {
                this.listeChoixPromotion.add(new SelectItem(p.getLibelle(), p.getLibelle()));
            }
        }
        return etudiants;
    }

    /**
     *
     * @param etudiants
     */
    public void setEtudiants(List<Etudiant> etudiants) {
        this.etudiants = etudiants;
    }

    /**
     *
     * @return
     */
    public Etudiant getEtudiant() {
        return etudiant;
    }

    /**
     *
     * @param etudiant
     */
    public void setEtudiant(Etudiant etudiant) {
        this.etudiant = etudiant;
    }

    /**
     *
     * @return listeChoixPromotion (List)
     */
    public List<SelectItem> getListeChoixPromotion() {
        return listeChoixPromotion;
    }

    /**
     *
     * @param listeChoixPromotion
     */
    public void setListeChoixPromotion(List<SelectItem> listeChoixPromotion) {
        this.listeChoixPromotion = listeChoixPromotion;
    }

    public void toogleMACAuthentification() {
        ReportActivityAuth raa = new ReportActivityAuth();
        try {
            ReportActivityAuth result = (ReportActivityAuth) em.createQuery("SELECT raa FROM ReportActivityAuth raa ORDER BY raa.dateEvent DESC").setMaxResults(1).getSingleResult();
            raa.setEnabled(!result.isEnabled());
        } catch (Exception ew) {
            raa.setEnabled(true);
        }
        try {
            tx.begin();
            em.persist(raa);
            tx.commit();
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success !", "Les changements réalisés ont été effectués avec succès"));
        } catch (Exception e) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Echec !", "Les changements réalisés n'ont pas été enregistrés"));
        }
    }

    /**
     *
     * @return listePromotionFilter (List)
     */
    public List<Promotion> getListePromotionFilter() {
        return listePromotionFilter;
    }

    /**
     *
     * @param listePromotionFilter
     */
    public void setListePromotionFilter(List<Promotion> listePromotionFilter) {
        this.listePromotionFilter = listePromotionFilter;
    }

    /**
     *
     * @return promotions (List)
     */
    public List<Promotion> getPromotions() {
        if (this.promotions == null || this.promotions.isEmpty()) {
            this.promotions = em.createQuery("SELECT p FROM Promotion p").getResultList();
        }
        return promotions;
    }

    /**
     *
     * @param promotions
     */
    public void setPromotions(List<Promotion> promotions) {
        this.promotions = promotions;
    }

    /**
     * Fonction qui permet de modifier le profil de l'administrateur connecté
     */
    public void modifierProfilAdmin() {
        try {
            tx.begin();
            em.merge(this.sessionBean.getAdmin());
            tx.commit();
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success !", "Les changements réalisés ont été effectués avec succès"));
        } catch (Exception e) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Echec !", "Les changements réalisés n'ont pas été enregistrés"));
        }
    }

    /**
     * Fonction qui vérifie la validité d'un mot de passe
     *
     * @param oldMdp représente l'ancien mot de passe et peut être mis à null
     * @return une liste d'erreurs. Si vide alors aucune erreur
     */
    private ArrayList<String> verifMDP() {
        ArrayList<String> errors = new ArrayList();
        if (this.password.length() < 6 || this.password.length() > 16) {
            errors.add("Entre 6 et 16 caractères");
        }

        if (!this.password.contains(" ")) {
            errors.add("Ne doit pas contenir d'espaces !");
        }

        return errors;
    }

    /**
     * Fonction qui modifie le mot de passe administrateur
     */
    public void modifierPassword() {
        List<String> errors = new ArrayList();
        if (!this.password.equals(this.confirmationPassword)) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Echec !", "La confirmation de mot de passe n'est pas identique"));
            return;
        }
        try {
            MessageDigest m;
            m = MessageDigest.getInstance("MD5");
            m.update(this.password.getBytes("UTF8"));
            byte s[] = m.digest();
            String result = "";

            for (int i = 0; i < s.length; i++) {
                result += Integer.toHexString((0x000000ff & s[i]) | 0xffffff00).substring(6);
            }
            this.password = result;
            errors = this.verifMDP();
            for (String e : errors) {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Echec !", e));
            }

            if (errors.isEmpty()) {
                this.sessionBean.getAdmin().setPassword(this.password);
                try {
                    tx.begin();
                    em.merge(this.sessionBean.getAdmin());
                    tx.commit();
                    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success !", "Votre mot de passe a été changé"));
                } catch (Exception e) {
                    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Echec !", e.getMessage()));
                }
            }
        } catch (NoSuchAlgorithmException ex) {
            Logger.getLogger(AdministrationBean.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UnsupportedEncodingException ex) {
            Logger.getLogger(AdministrationBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Fonction qui modifie la configuration
     *
     * @param conf
     */
    public void modifierConfig(Configuration conf) {
        try {
            //           Method validationMethod = DataValidation.class.getMethod(conf.getType().toLowerCase(), String.class);
            //           FacesMessage msg = (FacesMessage) validationMethod.invoke(DataValidation.class, conf.getValeur());

            if (true) {
                try {
                    tx.begin();
                    em.merge(conf);
                    tx.commit();
                    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success !", "La configuration a changé"));
                    PeriodicScanEJB.majInfos(this.configs);
                } catch (Exception e) {
                    FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Echec !", "Echec de la modification"));
                }
            } else {
                conf.setValeur(this.configBean.findByKey(conf.getCle()).getValeur());
                //               FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, msg.getSummary(), msg.getDetail()));
            }
//        } catch (NoSuchMethodException ex) {
//            Logger.getLogger(AdministrationBean.class.getName()).log(Level.SEVERE, null, ex);
        } catch (SecurityException ex) {
            Logger.getLogger(AdministrationBean.class.getName()).log(Level.SEVERE, null, ex);
//        } catch (IllegalAccessException ex) {
//            Logger.getLogger(AdministrationBean.class.getName()).log(Level.SEVERE, null, ex);
        } catch (IllegalArgumentException ex) {
            Logger.getLogger(AdministrationBean.class.getName()).log(Level.SEVERE, null, ex);
//        } catch (InvocationTargetException ex) {
//            Logger.getLogger(AdministrationBean.class.getName()).log(Level.SEVERE, null, ex);
        }
    }

    /**
     * Fonction qui modifie un étudiant
     */
    public void modifierEtudiant() {
        try {
            tx.begin();
            em.merge(this.etudiant);
            tx.commit();
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Infos :", "Modifications effectuées"));
        } catch (Exception e) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Erreur :", "Modifications non effectuées"));
        }
    }

    /**
     *
     * @param e
     */
    public void selectedEtudiant(Etudiant e) {
        this.etudiant = e;
    }

    /**
     *
     * @param m
     */
    public void selectedMachine(Machine m) {
        this.machine = m;
    }

    /**
     *
     * @param p
     */
    public void selectedPromotion(Promotion p) {
        this.promotion = p;
    }

    /**
     * Fonction qui supprime un étudiant
     */
    public void deleteEtudiant() {
        try {
            tx.begin();
            em.remove(this.em.find(Etudiant.class, this.etudiant.getIdPersonne()));
            tx.commit();
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Infos :", "Etudiant supprimé"));
        } catch (Exception ex) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Erreur :", "Echec de la suppression"));
        }
    }

    /**
     * Fonction qui supprime une machine
     */
    public String deleteMachine() {

        System.out.println(this.machine.getIdMachine() + " " + this.machine.getAdresseMAC());
        this.machine = em.find(Machine.class, this.machine.getIdMachine());
        machineBean.supprimerMachine(this.machine);
        
        return "student?faces-redirect=true";
        

    }

    /**
     * Fonction qui supprime une promotion
     */
    public void deletePromotion() {
        try {

            tx.begin();
            em.remove(this.em.find(Promotion.class, this.promotion.getIdPromotion()));
            tx.commit();
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success !", "La promotion a été supprimée avec ses élèves"));
        } catch (Exception e) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Echec !", "Echec de la suppression"));
        }
    }

    /**
     * Fonction qui ajoute une promotion
     */
    public void ajouterPromotion() {
        try {
            tx.begin();
            em.merge(this.promotion);
            tx.commit();
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success !", "La promotion a été ajoutée"));
        } catch (Exception e) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Echec !", "Echec de l'ajout"));
        }
    }

    /**
     *
     * @return
     */
    public Promotion getPromotion() {
        return promotion;
    }

    /**
     *
     * @param promotion
     */
    public void setPromotion(Promotion promotion) {
        this.promotion = promotion;
    }

    /**
     *
     * @return selectedPromotions (List)
     */
    public List<Promotion> getSelectedPromotions() {
        return selectedPromotions;
    }

    /**
     *
     * @param selectedPromotions
     */
    public void setSelectedPromotions(List<Promotion> selectedPromotions) {

        this.selectedPromotions = selectedPromotions;
    }

    /**
     *
     * @return selectedEtudiant (List)
     */
    public List<Etudiant> getSelectedEtudiant() {
        return selectedEtudiant;
    }

    /**
     *
     * @param selectedEtudiant
     */
    public void setSelectedEtudiant(List<Etudiant> selectedEtudiant) {
        this.selectedEtudiant = selectedEtudiant;
    }

    /**
     *
     * @return promosModel
     */
    public PromotionDataModel getPromoModel() {
        getPromotions();
        promosModel = new PromotionDataModel(this.promotions);
        return promosModel;
    }

    /**
     * fonction qui supprime une promotion prom
     *
     * @param prom
     */
    public void deletePromotions(Promotion prom) {
        try {
            tx.begin();
            em.refresh(this.em.find(Promotion.class, prom.getIdPromotion()));
            tx.commit();

            tx.begin();
            em.remove(this.em.find(Promotion.class, prom.getIdPromotion()));
            tx.commit();
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success !", "La promotion a été supprimée avec ses élèves"));
        } catch (Exception e) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Echec !", "Echec de la suppression"));
        }
    }

    /**
     * Fonction qui supprime un étudiant etu
     *
     * @param etu
     */
    public void deleteEtudiant(Etudiant etu) {
        //Query query = em.createQuery("SELECT m FROM Machine m WHERE m.etudiant.idPersonne=:idEtudiant")
        //        .setParameter("idEtudiant", etu.getIdPersonne());
        //lesMachines = query.getResultList();
        lesMachines = etu.getListeMachines();
        for (Machine m : lesMachines) {
            machineBean.supprimerMachine(m);
        }

        try {
            tx.begin();
            em.refresh(this.em.find(Etudiant.class, etu.getIdPersonne()));
            tx.commit();

            tx.begin();
            em.remove(this.em.find(Etudiant.class, etu.getIdPersonne()));
            tx.commit();
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Success !", "L'étudiant a été supprimée avec ses machines"));
        } catch (Exception e) {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Echec !", "Echec de la suppression"));
        }
    }
}
